﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using CoiffeurProject.Utils;
using CoiffeurProject.DBMS;
using CoiffeurProject.UserControls;
using System.ComponentModel;
using CoiffeurProject.DBMS.Entities;

namespace CoiffeurProject.Screens
{
    public partial class EmployeeScreen : Window
    {
        #region Fields

        Database db;
        CPScrollViewer largeSV, thinSV, notificationsSV;

        List<EmployeeSVEntry> sv_entries;
        List<EmployeeSVEntry> filtered_entries;
        EmployeeSVEntry selected;
        SearchBar searchBox;
        TicketButton list_btn, panel_btn, add_btn, modify_btn, delete_btn;
        ImageBrush panel_state_bg, no_panel_state_bg;
        FilterPanel filterPanel;
        EmployeeTableHeaders headers;
        NotificationBubble notification_bubble;
        LettersDashSlider slider;

        bool panelMode = false;

        #endregion

        public EmployeeScreen(Database db)
        {
            this.db = db;

            InitializeComponent();

            InitializeBackgrounds();

            InitializeUserControls();

            InitializeScrollViewer();

            InitializeNotificationsPanel();

            this.Show();
        }

        internal void Filter()
        {
            IEnumerable<EmployeeSVEntry> filtered_list = (IEnumerable<EmployeeSVEntry>)sv_entries;

            #region Searchbox Filter

            if (searchBox.TextBox.Text != "")
            {
                var text = searchBox.TextBox.Text.ToLower();
                filtered_list = filtered_list.Where(e => e.LinkedEmployee.FullName.ToLower().Contains(text)
                    || e.LinkedEmployee.Phone.Contains(text)
                    || e.LinkedEmployee.Age.ToString().Contains(text)
                    || e.LinkedEmployee.Address.ToLower().Contains(text)
                    || e.LinkedEmployee.Email.ToLower().Contains(text)
                    || e.LinkedEmployee.Notes.ToLower().Contains(text));
            }

            #endregion

            #region Combo Box Filter

            for (int i = 0; i < filterPanel.ComboBoxes.Count; i++)
            {
                switch (i)
                { 
                    case 0:
                        switch (filterPanel.ComboBoxes[i].SelectedIndex)
                        { 
                            case 1:
                                filtered_list = filtered_list.Where(e => e.LinkedEmployee.Sex == "Maschio");
                                break;
                            case 2:
                                filtered_list = filtered_list.Where(e => e.LinkedEmployee.Sex != "Maschio");
                                break;
                        }
                        break;
                    case 1:
                        switch (filterPanel.ComboBoxes[i].SelectedIndex)
                        {
                            case 1:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age <= 20).ToList();
                                break;
                            case 2:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age > 20 &&
                                        c.LinkedEmployee.Age <= 30).ToList();
                                break;
                            case 3:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age > 30 &&
                                        c.LinkedEmployee.Age <= 40).ToList();
                                break;
                            case 4:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age > 40 &&
                                        c.LinkedEmployee.Age <= 50).ToList();
                                break;
                            case 5:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age > 50 &&
                                        c.LinkedEmployee.Age <= 60).ToList();
                                break;
                            case 6:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Age > 60).ToList();
                                break;
                        }
                        break;
                    case 2:
                        switch (filterPanel.ComboBoxes[i].SelectedIndex)
                        {
                            case 1:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Frequency >= 10).ToList();
                                break;
                            case 2:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Frequency <= 9).ToList();
                                break;
                            case 3:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Frequency <= 5).ToList();
                                break;
                            case 4:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Frequency <= 3).ToList();
                                break;
                        }
                        break;
                    case 3:
                        switch (filterPanel.ComboBoxes[i].SelectedIndex)
                        {
                            case 1:
                                filtered_list = filtered_list.Where(c => c.LinkedEmployee.Debtor).ToList();
                                break;
                            case 2:
                                filtered_list = filtered_list.Where(c => !c.LinkedEmployee.Debtor).ToList();
                                break;
                        }
                        break;
                }
            }

            #endregion

            #region Table Headers Filter

            switch (headers.LastClicked)
            {
                case 1: filtered_list = filtered_list.OrderBy(e => e.LinkedEmployee.FullName); break;
                case 2: filtered_list = filtered_list.OrderByDescending(e => e.LinkedEmployee.FullName); break;
                case 3: filtered_list = filtered_list.OrderBy(e => e.LinkedEmployee.Phone); break;
                case 4: filtered_list = filtered_list.OrderByDescending(e => e.LinkedEmployee.Phone); break;
                case 5: filtered_list = filtered_list.OrderBy(e => e.LinkedEmployee.Address); break;
                case 6: filtered_list = filtered_list.OrderByDescending(e => e.LinkedEmployee.Address); break;
                case 7: filtered_list = filtered_list.OrderBy(e => e.LinkedEmployee.Age); break;
                case 8: filtered_list = filtered_list.OrderByDescending(e => e.LinkedEmployee.Age); break;
                case 9: filtered_list = filtered_list.OrderBy(e => e.LinkedEmployee.Frequency); break;
                case 10: filtered_list = filtered_list.OrderByDescending(e => e.LinkedEmployee.Frequency); break;
            }

            #endregion

            if (!filtered_list.Contains(selected) && selected != null) { selected.Entry.ToggleSelected(); selected = null; }

            filtered_entries = filtered_list.ToList();

            if (panelMode)
                FillThinSVWithFilteredData();
            else
                FillLargeSVWithFilteredData();
        }

        #region Private Methods

        private void InitializeBackgrounds()
        {
            panel_state_bg = new ImageBrush()
            {
                ImageSource = new BitmapImage(new Uri(
                    @"pack://application:,,,/CoiffeurProject;component/Images/Employee/Main/background_with_panel.JPG")),
                Stretch = Stretch.Uniform
            };

            no_panel_state_bg = new ImageBrush()
            {
                ImageSource = new BitmapImage(new Uri(
                    @"pack://application:,,,/CoiffeurProject;component/Images/Employee/Main/background_without_panel.JPG")),
                Stretch = Stretch.Uniform
            };
        }

        private void InitializeUserControls()
        {
            #region Exit Button

            var exit_button = new CloseButton(this, new Thickness(625, 40, 0, 0), 0, 2);

            main_container.Children.Add(exit_button.MainContainer);

            #endregion

            #region Searchbox

            searchBox = new SearchBar(new Thickness(32, 41, 0, 0), 0, 0);
            searchBox.TextBox.TextChanged += new TextChangedEventHandler(
                delegate(object sender, TextChangedEventArgs e)
                {
                    Filter();
                });

            main_container.Children.Add(searchBox.MainContainer);

            #endregion

            #region Ticket Buttons

            list_btn = new TicketButton(new Thickness(282, 15, 0, 0), "Lista",
                @"pack://application:,,,/CoiffeurProject;component/Images/Customer/Icons/list.PNG",
                delegate(object sender, RoutedEventArgs e)
                {
                    if (panelMode)
                    {
                        largeSV.ScrollViewer.Visibility = Visibility.Visible;
                        thinSV.ScrollViewer.Visibility = Visibility.Hidden;

                        FillLargeSVWithFilteredData();
                        Background = no_panel_state_bg;

                        panelMode = !panelMode;
                    }
                });

            Grid.SetColumn(list_btn.MainContainer, 2);
            Grid.SetRow(list_btn.MainContainer, 1);

            main_container.Children.Add(list_btn.MainContainer);

            panel_btn = new TicketButton(new Thickness(282 + 124, 15, 0, 0), "Pannello",
                @"pack://application:,,,/CoiffeurProject;component/Images/Customer/Icons/panel.PNG",
                delegate(object sender, RoutedEventArgs e)
                {
                    if (!panelMode)
                    {
                        largeSV.ScrollViewer.Visibility = Visibility.Hidden;
                        if (thinSV == null)
                            InitializeThinSV();
                        else
                        {
                            thinSV.ScrollViewer.Visibility = Visibility.Visible;
                            FillThinSVWithFilteredData();
                        }

                        Background = panel_state_bg;

                        panelMode = !panelMode;
                    }
                });

            Grid.SetColumn(panel_btn.MainContainer, 2);
            Grid.SetRow(panel_btn.MainContainer, 1);

            main_container.Children.Add(panel_btn.MainContainer);

            add_btn = new TicketButton(new Thickness(282, 153, 0, 0), "Nuovo cliente",
                @"pack://application:,,,/CoiffeurProject;component/Images/Customer/Icons/add.PNG",
                delegate(object sender, RoutedEventArgs e)
                {
                    CustomerForm form = new CustomerForm(db);
                    this.DisableForegroundWindow(form);
                    form.Closing += new System.ComponentModel.CancelEventHandler(delegate(object s, CancelEventArgs ee)
                    {
                        
                    });
                });

            Grid.SetColumn(add_btn.MainContainer, 2);
            Grid.SetRow(add_btn.MainContainer, 1);

            main_container.Children.Add(add_btn.MainContainer);

            modify_btn = new TicketButton(new Thickness(282 + 128, 153, 0, 0), "Modifica",
                @"pack://application:,,,/CoiffeurProject;component/Images/Customer/Icons/modify.PNG",
                delegate(object sender, RoutedEventArgs e)
                {
                });

            Grid.SetColumn(modify_btn.MainContainer, 2);
            Grid.SetRow(modify_btn.MainContainer, 1);

            main_container.Children.Add(modify_btn.MainContainer);

            delete_btn = new TicketButton(new Thickness(282 + 1 + 128 * 2, 153, 0, 0), "Elimina",
                @"pack://application:,,,/CoiffeurProject;component/Images/Customer/Icons/delete.PNG",
                delegate(object sender, RoutedEventArgs e)
                {
                });

            Grid.SetColumn(delete_btn.MainContainer, 2);
            Grid.SetRow(delete_btn.MainContainer, 1);

            main_container.Children.Add(delete_btn.MainContainer);

            #endregion

            #region Table Headers

            headers = new EmployeeTableHeaders(this, 1, 0, 3, 0);
            main_container.Children.Add(headers.MainContainer);

            #endregion

            #region Filter Panel

            filterPanel = new FilterPanel(new Thickness(280, 291, 0, 0), 1, 2,
                new List<List<string>>() {
                    new List<string>() { "Uomini e Donne", "Solo Uomini", "Solo Donne" },
                    new List<string>() { "Tutte le età", "Fino a 20 anni", "Da 20 a 30 anni", "Da 30 a 40 anni", "Da 40 a 50 anni", "Da 50 a 60 anni", "Più di 60 anni"},
                    new List<string>() { "Qualsiasi frequenza", "10 o più volte in un anno", "Fino a 9 volte in un anno", "Fino a 5 volte in un anno", "Fino a 3 volte in un anno" },
                    new List<string>() { "Status del conto", "Debitori", "Saldati" }
                },
                new List<Action<object, SelectionChangedEventArgs>> { 
                    delegate(object s, SelectionChangedEventArgs a) { Filter(); },
                    delegate(object s, SelectionChangedEventArgs a) { Filter(); },
                    delegate(object s, SelectionChangedEventArgs a) { Filter(); },
                    delegate(object s, SelectionChangedEventArgs a) { Filter(); } 
                },
                delegate(object s, RoutedEventArgs a) { });

            main_container.Children.Add(filterPanel.MainContainer);

            #endregion

            #region Letter Dashboard

            slider = new LettersDashSlider(0, 2, 3, 0);
            slider.LeftArrow.Click += new RoutedEventHandler(delegate(object s, RoutedEventArgs a) { var y = GetScrollViewerYOffset(slider.SelectedLetter); if (panelMode) thinSV.MoveToYCoord(y); else largeSV.MoveToYCoord(y); });
            slider.RightArrow.Click += new RoutedEventHandler(delegate(object s, RoutedEventArgs a) { var y = GetScrollViewerYOffset(slider.SelectedLetter); if (panelMode) thinSV.MoveToYCoord(y); else largeSV.MoveToYCoord(y); });
            main_container.Children.Add(slider.MainContainer);

            #endregion
        }

        private void InitializeThinSV()
        {
            largeSV.ResetEntries();

            thinSV = new CPScrollViewer(new Thickness(51, 80, 0, 0), 380, 907, 0, 1, 3, 0);

            //if (filtered_entries == null)
            //    FillThinSV();
            //else
                FillThinSVWithFilteredData();

            main_container.Children.Add(thinSV.ScrollViewer);
        }

        private void InitializeScrollViewer()
        {
            largeSV = new CPScrollViewer(new Thickness(51, 80, 0, 0), 1423, 907, 0, 1, 3, 0);

            sv_entries = new List<EmployeeSVEntry>();

            for (int i = 0; i < db.Employees.List.Count; i++)
            {
                sv_entries.Add(new EmployeeSVEntry(this, db.Employees.List[i], true));
                largeSV.AddEntry(sv_entries[i].Entry);
            }

            main_container.Children.Add(largeSV.ScrollViewer);
        }

        private void InitializeNotificationsPanel()
        {
            notification_bubble = new NotificationBubble(new Thickness(294, 572, 0, 0),
                db.Notifications.CustomersNotifications.Count, 38, 38, 1, 2);

            main_container.Children.Add(notification_bubble.MainContainer);

            notificationsSV = new CPScrollViewer(new Thickness(292, 627, 0, 0), 370, 357, 2, 1);

            main_container.Children.Add(notificationsSV.ScrollViewer);

            FillNotificationsSV();
        }

        private void FillNotificationsSV()
        {
            for (int i = 0; i < db.Notifications.CustomersNotifications.Count; i++)
            {
                notificationsSV.AddEntry(new ScrollViewerNotificationEntry(db.Notifications
                    .EmployeesNotifications[i].Description));
            }
        }

        private void FillLargeSV()
        {
            thinSV.ResetEntries();

            for (int i = 0; i < sv_entries.Count; i++)
            {
                sv_entries[i].UnhideLabels();
                largeSV.AddEntry(sv_entries[i].Entry);
            }
        }

        private void FillThinSV()
        {
            largeSV.ResetEntries();

            for (int i = 0; i < sv_entries.Count; i++)
            {
                sv_entries[i].HideLabels();
                thinSV.AddEntry(sv_entries[i].Entry);
            }
        }

        private void FillLargeSVWithFilteredData()
        {
            if (filtered_entries != null)
            {
                thinSV.ResetEntries();
                largeSV.ResetEntries();

                for (int i = 0; i < filtered_entries.Count; i++)
                {
                    filtered_entries[i].UnhideLabels();
                    largeSV.AddEntry(filtered_entries[i].Entry);
                }
            }
            else
                FillLargeSV();
        }

        private void FillThinSVWithFilteredData()
        {
            if (filtered_entries != null)
            {
                largeSV.ResetEntries();
                thinSV.ResetEntries();

                for (int i = 0; i < filtered_entries.Count; i++)
                {
                    filtered_entries[i].HideLabels();
                    thinSV.AddEntry(filtered_entries[i].Entry);
                }
            }
            else
                FillThinSV();
        }

        public int GetScrollViewerYOffset(char letter)
        {
            int offset = 53;
            var list = filtered_entries != null ? filtered_entries : sv_entries;

            var index = list.FindIndex(c => c.LinkedEmployee.Name.ToLower()[0] == letter);

            if (index == -1)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    index = i;

                    if (letter < list[i].LinkedEmployee.Name.ToLower()[0])
                        break;
                }
            }

            return offset * index;
        }

        #endregion

        #region Properties

        internal EmployeeSVEntry Selected
        {
            get { return selected; }
            set { selected = value; }
        }

        #endregion
    }

    #region Support Classes

    internal class EmployeeSVEntry
    {
        EmployeeScreen emplScreen;
        ScrollViewerEntry entry;
        Employee employee;
        Grid main_container;
        Label name, phone, address, age, returned;

        internal EmployeeSVEntry(EmployeeScreen emplScreen, Employee employee, bool largeEntry)
        {
            this.emplScreen = emplScreen;
            this.employee = employee;

            main_container = new Grid()
            {
                Width = largeEntry ? 1388 : 364,
                Height = 50,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            #region Labels

            name = new Label()
            {
                Content = employee.FullName.Length > 17 ? employee.FullName.Substring(0, 14) + "..." : 
                    employee.FullName,
                FontSize = 24,
                HorizontalContentAlignment = HorizontalAlignment.Left,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Left,
                Margin = new Thickness(10, 0, 0, 0),
                Width = largeEntry ? 230 : 344
            };

            Grid.SetRow(name, 0);
            Grid.SetColumn(name, 0);
            main_container.Children.Add(name);

            phone = new Label()
            {
                Content = employee.Phone,
                FontSize = 24,
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Left,
                Margin = new Thickness(240, 0, 0, 0),
                Width = 190
            };

            Grid.SetRow(phone, 0);
            Grid.SetColumn(phone, 0);
            main_container.Children.Add(phone);

            address = new Label()
            {
                Content = employee.Address.Length > 20 ? employee.Address.Substring(0, 17) + "..." : 
                    employee.Address,
                FontSize = 24,
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Left,
                Margin = new Thickness(440, 0, 0, 0),
                Width = 230
            };

            Grid.SetRow(address, 0);
            Grid.SetColumn(address, 0);
            main_container.Children.Add(address);

            age = new Label()
            {
                Content = employee.Age,
                FontSize = 24,
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Left,
                Margin = new Thickness(680, 0, 0, 0),
                Width = 235
            };

            Grid.SetRow(age, 0);
            Grid.SetColumn(age, 0);
            main_container.Children.Add(age);

            returned = new Label()
            {
                Content = "NP",
                FontSize = 24,
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Left,
                Margin = new Thickness(930, 0, 0, 0),
                Width = 270
            };

            Grid.SetRow(returned, 0);
            Grid.SetColumn(returned, 0);
            main_container.Children.Add(returned);

            #endregion

            entry = new ScrollViewerEntry(main_container, ImagesPath.SelectedCustomer, largeEntry ? 1388 : 364, 53);
            
            entry.AddClickHandlers(delegate(object s, RoutedEventArgs e)
            {
                if (emplScreen.Selected != null) emplScreen.Selected.Entry.ToggleSelected();
                emplScreen.Selected = this;
                entry.ToggleSelected();
            });
        }

        internal void HideLabels()
        {
            main_container.Width = 344;
            phone.Visibility = Visibility.Hidden;

            entry.Rollover.Width = 344;
            entry.Selected.Width = 344;
        }

        internal void UnhideLabels()
        {
            main_container.Width = 1388;
            phone.Visibility = Visibility.Visible;

            entry.Rollover.Width = 1388;
            entry.Selected.Width = 1388;
        }

        internal ScrollViewerEntry Entry
        {
            get { return entry; }
        }

        public Employee LinkedEmployee
        {
            get { return employee; }
        }
    }

    #endregion
}
